package com.cims.bpm.security.utils.certification;

import java.io.BufferedReader;
import java.io.FileReader;

import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.x509.Certificate;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.util.encoders.Hex;

import com.cims.bpm.security.utils.sm2.Sm2Utils;
/**
 * SM2 证书工具类
 *
 */
public class Sm2CertUtils {

	private static final Logger logger = Logger.getLogger(Sm2CertUtils.class);

	/**
	 * 从公钥证书中获取公钥
	 * @param filePath
	 * @return 公钥参数对象
	 */
	public static CipherParameters getPubKeyFPubCert(String filePath) {
		CipherParameters cipherParameters = null;
		try {
			byte[] csCert = readFile(filePath);
			csCert = Base64.decodeBase64(csCert);
			Certificate cert = certFrom(csCert);	
			logger.debug("public cert：" + Hex.toHexString(getPublicKey(cert)));

			SubjectPublicKeyInfo subjectPublicKeyInfo = cert.getSubjectPublicKeyInfo();
			DERBitString publicKeyData = subjectPublicKeyInfo.getPublicKeyData();
			byte[] publicKey = publicKeyData.getEncoded();
			byte[] encodedPublicKey = publicKey;
			byte[] ecP = new byte[64];
			System.arraycopy(encodedPublicKey, 4, ecP, 0, ecP.length);
			System.out.println("public Key：" + Hex.toHexString(ecP));
			logger.debug("public Key：" + Hex.toHexString(ecP));
			
			byte[] certPKX = new byte[32];
			byte[] certPKY = new byte[32];
			System.arraycopy(ecP, 0, certPKX, 0, 32);
			System.arraycopy(ecP, 32, certPKY, 0, 32);
			cipherParameters = Sm2Utils.sm2PubKeyGet(certPKX, certPKY);
		} catch (Exception e) {
			logger.error("Fail: get public key from certificate", e);
		}
		return cipherParameters;
	}

	private static byte[] readFile(String filePath) {
		BufferedReader br = null;
		StringBuilder sb = new StringBuilder();
		try {
			br = new BufferedReader(new FileReader(filePath));
			String readLine = null;
			while ((readLine = br.readLine()) != null) {
				if (readLine.startsWith("--")) {
					continue;
				}
				sb.append(readLine);
			}
		} catch (Exception e) {
			logger.error("Fail: readFile", e);
		}
		return sb.toString().getBytes();
	}

	
	
	
	private static final Certificate certFrom(byte[] certData) throws Exception {
		Certificate cert = null;
		try {
			ASN1Sequence seq = ASN1Sequence.getInstance(certData);
			cert = Certificate.getInstance(seq);
		} catch (Exception ex) {
			throw new Exception(ex);
		}
		
		return cert;
	}

	private static byte[] getPublicKey(Certificate cert) {
		byte[] pubData = cert.getSubjectPublicKeyInfo().getPublicKeyData().getBytes();
		byte[] pk = new byte[64];
		if (pubData.length == 64) {
			System.arraycopy(pubData, 0, pk, 0, 64);
		} else if (pubData.length == 65) {
			System.arraycopy(pubData, 1, pk, 0, 64);
		} else if (pubData.length == 66) {
			System.arraycopy(pubData, 2, pk, 0, 64);
		} else {
			return null;
		}
		return pk;
	}

	

}
